package utils;

import com.alibaba.fastjson.JSONObject;
import entity.BodyParts;
import entity.ResponseData;

import java.net.URLEncoder;
import java.util.ArrayList;

public class FallDetectionImproveUtils {

    /**
     *
     * @param top_head_x    头顶横坐标
     * @param top_head_y    头顶纵坐标
     * @param neck_x    颈部横坐标
     * @param neck_y    颈部纵坐标
     * @param left_hip_x    左髋横坐标
     * @param left_hip_y    左髋纵坐标
     * @param right_hip_x   右髋横坐标
     * @param right_hip_y   右髋纵坐标
     * @param left_knee_x   左膝横坐标
     * @param left_knee_y   左膝纵坐标
     * @param right_knee_x  右膝横坐标
     * @param right_knee_y  右膝纵坐标
     * @param left_ankle_x  左脚踝横坐标
     * @param left_ankle_y  左脚踝纵坐标
     * @param right_ankle_x 右脚踝横坐标
     * @param right_ankle_y 右脚踝纵坐标
     * @return  true为摔倒 false为未摔倒
     */
    public static boolean isFallImprove(double top_head_x,double top_head_y,
                                        double neck_x,double neck_y,
                                        double left_hip_x,double left_hip_y,
                                        double right_hip_x,double right_hip_y,
                                        double left_knee_x,double left_knee_y,
                                        double right_knee_x,double right_knee_y,
                                        double left_ankle_x,double left_ankle_y,
                                        double right_ankle_x,double right_ankle_y){
        //  计算髋部中间点
        double middle_hip_x = (left_hip_x + right_hip_x)/2;
        double middle_hip_y = (left_hip_y + right_hip_y)/2;

        //  计算膝盖中间点
        double middle_knee_x = (left_knee_x + right_knee_x)/2;
        double middle_knee_y = (left_knee_y + right_knee_y)/2;

        //  计算脚踝中间点
        double middle_ankle_x = (left_ankle_x+right_ankle_x)/2;
        double middle_ankle_y = (left_ankle_y+right_ankle_y)/2;


        //  头比脚低，认为摔倒
        if (top_head_y < middle_ankle_y){
            return true;
        }

        //  躯干与水平方向垂直，认为站立
        if (neck_x == middle_hip_x){
            return false;
        }

        //  腿部与水平方向垂直，认为站立
        if (middle_knee_x == middle_ankle_x){
            return false;
        }

        //  计算颈部与髋部中间点连线的正切值
        double tan1 = Math.abs(neck_y - middle_hip_y) / Math.abs(neck_x - middle_hip_x);
        //  计算颈部与髋部中间点连线与水平方向的夹角——躯干角度
        double trunk_angle = Math.toDegrees(Math.atan(tan1));

        //  计算膝盖中间点与脚踝中间点的正切值
        double tan2 = Math.abs(middle_knee_y - middle_ankle_y) / Math.abs(middle_knee_x - middle_ankle_x);
        //  计算膝盖中间点与脚踝中间点的连线与水平方向的夹角——腿部角度
        double leg_angle = Math.toDegrees(Math.atan(tan2));

        //  判断,如果躯干或腿部存在夹角小于45度，认为摔倒
        if (trunk_angle < 45.0 || leg_angle<45.0){
            return true;
        }else{
            return false;
        }
    }

    /**
     *
     * @param filePath 单张图片的本地路径
     * @return true为摔倒，false为为摔倒
     */
    public static boolean detectOnePhotoImprove(String filePath){
        // 请求url
        String url = "https://aip.baidubce.com/rest/2.0/image-classify/v1/body_analysis";

        try {
            byte[] imgData = FileUtil.readFileByBytes(filePath);
            String imgStr = Base64Util.encode(imgData);
            String imgParam = URLEncoder.encode(imgStr, "UTF-8");

            String param = "image=" + imgParam;

            // 注意这里仅为了简化编码每一次请求都去获取access_token，线上环境access_token有过期时间， 客户端可自行缓存，过期后重新获取。
            String accessToken = "24.9eeb2842c1d2c6000e48c524aae4922e.2592000.1629264825.282335-24569897";

            //  单张图片的检测返回结果
            Thread.sleep(500);
            String result = HttpUtil.post(url, accessToken, param);

            //  将JSON字符串序转换成对象
            ResponseData responseData = JSONObject.parseObject(result, ResponseData.class);
            //  拿到相应坐标
            BodyParts bodyParts = responseData.getPersonInfo()[0].getBodyParts();

            double top_head_x = bodyParts.getTop_head().getX();
            double top_head_y = -bodyParts.getTop_head().getY();

            double neck_x = bodyParts.getNeck().getX();
            double neck_y = -bodyParts.getNeck().getY();

            double left_hip_x = bodyParts.getLeft_hip().getX();
            double left_hip_y = -bodyParts.getLeft_hip().getY();

            double right_hip_x = bodyParts.getRight_hip().getX();
            double right_hip_y = -bodyParts.getRight_hip().getY();

            double left_knee_x = bodyParts.getLeft_knee().getX();
            double left_knee_y = -bodyParts.getLeft_knee().getY();

            double right_knee_x = bodyParts.getRight_knee().getX();
            double right_knee_y = -bodyParts.getRight_knee().getY();

            double left_ankle_x = bodyParts.getLeft_ankle().getX();
            double left_ankle_y = -bodyParts.getLeft_ankle().getY();

            double right_ankle_x = bodyParts.getRight_ankle().getX();
            double right_ankle_y = -bodyParts.getRight_ankle().getY();

            boolean isFall = FallDetectionImproveUtils.isFallImprove(top_head_x,top_head_y,neck_x,neck_y,left_hip_x,left_hip_y,right_hip_x,right_hip_y,left_knee_x,left_knee_y,right_knee_x,right_knee_y,left_ankle_x,left_ankle_y,right_ankle_x,right_ankle_y);

            //  摔倒了
            if (isFall == true){
                return true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        //  没摔倒
        return false;
    }


    /**
     * 批量摔倒检测
     * @param path 测试目录文件夹的本地位置
     */
    public static void detectByDirectoryImprove(String path){
        //  定义的临时变量，用来记录有几张图片是摔倒的
        int temp = 0;
        // 请求url
        String url = "https://aip.baidubce.com/rest/2.0/image-classify/v1/body_analysis";
        ArrayList<String> fileNames = new ArrayList<>();
        //  获取文件夹目录下的所有图片名称
        FileUtil.getAllFileName(path,fileNames);
        for (String fileName : fileNames) {
            //  获取图片的相对路径
            String filePath = path+"\\"+fileName;

            try {
                byte[] imgData = FileUtil.readFileByBytes(filePath);
                String imgStr = Base64Util.encode(imgData);
                String imgParam = URLEncoder.encode(imgStr, "UTF-8");

                String param = "image=" + imgParam;

                // 注意这里仅为了简化编码每一次请求都去获取access_token，线上环境access_token有过期时间， 客户端可自行缓存，过期后重新获取。
                String accessToken = "24.9eeb2842c1d2c6000e48c524aae4922e.2592000.1629264825.282335-24569897";

                //  单张图片的检测返回结果
                Thread.sleep(800);
                String result = HttpUtil.post(url, accessToken, param);

                //  将JSON字符串序转换成对象
                ResponseData responseData = JSONObject.parseObject(result, ResponseData.class);
                //  拿到相应坐标
                //  拿到相应坐标
                BodyParts bodyParts = responseData.getPersonInfo()[0].getBodyParts();

                double top_head_x = bodyParts.getTop_head().getX();
                double top_head_y = -bodyParts.getTop_head().getY();

                double neck_x = bodyParts.getNeck().getX();
                double neck_y = -bodyParts.getNeck().getY();

                double left_hip_x = bodyParts.getLeft_hip().getX();
                double left_hip_y = -bodyParts.getLeft_hip().getY();

                double right_hip_x = bodyParts.getRight_hip().getX();
                double right_hip_y = -bodyParts.getRight_hip().getY();

                double left_knee_x = bodyParts.getLeft_knee().getX();
                double left_knee_y = -bodyParts.getLeft_knee().getY();

                double right_knee_x = bodyParts.getRight_knee().getX();
                double right_knee_y = -bodyParts.getRight_knee().getY();

                double left_ankle_x = bodyParts.getLeft_ankle().getX();
                double left_ankle_y = -bodyParts.getLeft_ankle().getY();

                double right_ankle_x = bodyParts.getRight_ankle().getX();
                double right_ankle_y = -bodyParts.getRight_ankle().getY();

                boolean isFall = FallDetectionImproveUtils.isFallImprove(top_head_x,top_head_y,neck_x,neck_y,left_hip_x,left_hip_y,right_hip_x,right_hip_y,left_knee_x,left_knee_y,right_knee_x,right_knee_y,left_ankle_x,left_ankle_y,right_ankle_x,right_ankle_y);
                if (isFall == true){
                    System.out.println(filePath+"中的人可能摔倒了！");
                    temp++;
                }else {
                    System.out.println(filePath+"中的人应该没有摔倒！！");
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        System.out.println("一种有"+temp+"张图片识别出来是摔倒的!");
    }

}
